package cn.itsource.ymcc.controller;

import cn.itsource.ymcc.aggregation.AggrPageList;
import cn.itsource.ymcc.aggregation.AggrTermsBucket;
import cn.itsource.ymcc.domain.CourseDoc;
import cn.itsource.ymcc.mapper.HighlightResultMapper;
import cn.itsource.ymcc.query.CourseDocQuery;
import cn.itsource.ymcc.repository.CourseElasticsearchRepository;
import cn.itsource.ymcc.result.JsonResult;
import com.alibaba.fastjson.JSON;
import org.apiguardian.api.API;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/search/course")
public class SearchCourseController {
    @Autowired
    private CourseElasticsearchRepository courseElasticsearchRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @PostMapping("/queryCourseDocByIds")
    public JsonResult queryCourseDocByIds(@RequestBody List<Long> ids){
        Iterable<CourseDoc> allById = courseElasticsearchRepository.findAllById(ids);
        return JsonResult.success().setData(JSON.toJSONString(allById));
    }


    @GetMapping("/{courseId}")
    public JsonResult queryCourseDoc(@PathVariable("courseId") Long courseId){
        //Optional java8的新特性 主要的作用 优雅的解决空指针异常
        Optional<CourseDoc> byId = courseElasticsearchRepository.findById(courseId);
        return JsonResult.success().setData(JSON.toJSONString(byId.get()));
    }

    @PostMapping("/save")
    public JsonResult save(@RequestBody CourseDoc courseDoc){
        if (courseDoc != null) {
            courseElasticsearchRepository.save(courseDoc);
            System.out.println("成功");
        }
        return JsonResult.success();
    }

    @PostMapping("/bathSave")
    public JsonResult save(@RequestBody List<CourseDoc> courseDoc){
        courseDoc.forEach(course -> courseElasticsearchRepository.save(course));
        return JsonResult.success();
    }

    @DeleteMapping("/del/{id}")
    public JsonResult save(@PathVariable("id") Long id){
        courseElasticsearchRepository.deleteById(id);
        return JsonResult.success();
    }

    @PostMapping("/queryCourse")
    public JsonResult query(@RequestBody CourseDocQuery courseDocQuery){
        //第一层 query
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();

        // bool
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        //设置查询条件
        if(StringUtils.hasText(courseDocQuery.getKeyword()) && !"null".equals(courseDocQuery.getKeyword())){
            bool.filter().add(QueryBuilders.matchQuery("name",courseDocQuery.getKeyword()));
        }
        if (StringUtils.hasText(courseDocQuery.getGradeName())){
            bool.filter().add(QueryBuilders.matchQuery("gradeName", courseDocQuery.getGradeName()));
        }
        if(courseDocQuery.getGradeId() != null){
            bool.filter().add(QueryBuilders.matchQuery("gradeId",courseDocQuery.getGradeId()));
        }


        queryBuilder.withQuery(bool);

        //聚合查询,按照机构名字聚合，按照数量倒排
        queryBuilder.addAggregation(AggregationBuilders
                .terms("gradeNamexAgg") //聚合名字
                .field("gradeName.keyword")	//聚合的字段
                .order(BucketOrder.count(false)).size(20));//排序后取前20条
        //聚合查询,按照机构名字聚合，按照数量倒排
        queryBuilder.addAggregation(AggregationBuilders
                .terms("forUserAgg") //聚合名字
                .field("forUser.keyword")	//聚合的字段
                .order(BucketOrder.count(false)).size(20));//排序后取前20条
        //聚合查询,按照机构名字聚合，按照数量倒排
        queryBuilder.addAggregation(AggregationBuilders
                .terms("courseTypeNameAgg") //聚合名字
                .field("courseTypeName.keyword")	//聚合的字段
                .order(BucketOrder.count(false)).size(20));//排序后取前20条




        //设置分页
        //分页  注意：SpringDataElasticsearch的当前页码是从0开始的
        Pageable pageable = PageRequest.of(courseDocQuery.getPageNo()-1, courseDocQuery.getPageSize());
        queryBuilder.withPageable(pageable);

        //设置es的排序
        if(StringUtils.hasText(courseDocQuery.getOrderField())){
            SortOrder sortOrder = SortOrder.ASC;
            if("desc".equalsIgnoreCase(courseDocQuery.getOrderType())){
                sortOrder = SortOrder.DESC;
            }
            SortBuilder sortBuilder = SortBuilders
                    .fieldSort(courseDocQuery.getOrderField()) //设置排序的字段
                    .order(sortOrder);//设置排序方式
            queryBuilder.withSort(sortBuilder);
        }


        //设置高亮显示
        HighlightBuilder.Field  highlightField = new HighlightBuilder.Field("name")
                .preTags("<span style='color:red'>")
                .postTags("</span>");
        queryBuilder.withHighlightFields(highlightField);


        //最后面  查询数据
        AggregatedPage<CourseDoc> page = elasticsearchRestTemplate.queryForPage(queryBuilder.build(), CourseDoc.class, highlightResultMapper);
        Map<String, List<AggrTermsBucket>> aggrResult = getAggrResult(page);

//        Page<CourseDoc> page = courseElasticsearchRepository.search(queryBuilder.build());
        System.out.println("当前页码："+page.getNumber());
        System.out.println("每页条数："+page.getSize());
        System.out.println("总条数："+page.getTotalElements());
        System.out.println("总页数："+page.getTotalPages());
        System.out.println("当前页条数："+page.getNumberOfElements());

        AggrPageList aggrPageList = new AggrPageList(page.getTotalElements(),page.getContent(),aggrResult);
        return JsonResult.success().setData(aggrPageList);
    }


    private Map<String, List<AggrTermsBucket>> getAggrResult(AggregatedPage<CourseDoc> page) {
        //用来封装聚合结果
        Map<String,List<AggrTermsBucket>> aggrMap = new HashMap<>();

        //遍历聚合结果
        Aggregations aggregations = page.getAggregations();

        Map<String, Aggregation> stringAggregationMap = aggregations.asMap();

        Set<Map.Entry<String, Aggregation>> entries = stringAggregationMap.entrySet();

        entries.forEach(e->{
            //集合的名字
            String key = e.getKey();
            //集合的值的处理
            ParsedStringTerms value = (ParsedStringTerms)e.getValue();
            List<? extends Terms.Bucket> buckets = value.getBuckets();

            //使用lomda 把  List<StringTerms.Bucket>  转成  List<AggrTermsVo>
            List<AggrTermsBucket> aggrTermsVos = buckets.stream().map(bucket -> {
                return new AggrTermsBucket(bucket.getKeyAsString(), bucket.getDocCount());
            }).collect(Collectors.toList());

            aggrMap.put(key, aggrTermsVos);
        });
        return aggrMap;
    }

}
